@TOC
前言
之前使用的eureka/hystrix 都是调用RestTemplate(繁琐 重复高) 。而OpenFeign对请求进行简化(实际上就是对之前请求的一个封装)。Feign停更了 OpenFeign是在Feign基础上开发出来的。
常用的几种接口调用方法:
- Httpclient 易用 灵活
- Okhttp 处理网络请求 轻量级 支持多协议。。
- HttpURLConnection 使用复杂
- RestTemplate Rest服务的客户端 提供多种便携访问HTTP服务的方法
1.HelloWorld
还是继续使用之前的 provider 和 eureka配置,重新建一个spring boot项目,创建时选OpenFeign 依赖。如下:
创建成功后,在application.properties中添加如下配置:
spring.application.name=openfeign server.port=5000 eureka.client.service-url.defaultZone=http://localhost:1111/eureka
|
接下来,在项目启动类上面添加注解,开启Feign的支持:
@SpringBootApplication @EnableFeignClients public class OpenfeignApplication {
public static void main(String[] args) { SpringApplication.run(OpenfeignApplication.class, args); } }
|
定义HelloService 接口,使用OpenFeign:
@FeignClient("provider") public interface HelloService {
@GetMapping("/hello") String hello(); }
|
最后调用 HelloController 中,调用 HelloService 进行测试:
@RestController public class HelloController {
@Autowired HelloService helloService;
@GetMapping("/hello") public String hello(){ return helloService.hello(); } }
|
2.参数传递
和普通参数传递的区别:
- 参数一定要绑定参数名
- 如果通过Header来传递参数,一定要中文转码
测试的服务端接口,继续使用 provider 的接口;然后,在 openFeign 中添加调用接口即可。
@FeignClient("provider") public interface HelloService {
@GetMapping("/hello") String hello();
@GetMapping("/hello2") String hello2(@RequestParam("name") String name);
@PostMapping("/user2") User addUser(@RequestBody User user);
@DeleteMapping("/user14/{id}") void deleteUserById(@PathVariable("id") Integer id);
@GetMapping("/user3") void getUserByName(@RequestHeader("name") String name); }
|
注意:凡是k/v形式的参数,要标记参数名称。
然后分别启动 Eureka、Provider、OpenFeign,访问 http://localhost:5000/hello ,控制台如下:
3.继承特性
将 provider 和 openfeign 中公共的部分提取出来一起使用。
新建一个Moudule ,叫做 first-api,由于这个模块要被其它模块所依赖,所以这个模块是一个maven项目,还有用springmvc的东西,因此在创建成功后,要添加 web 依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.0.RELEASE</version> </dependency> <dependency> <groupId>com.example</groupId> <artifactId>commons</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
|
然后定义公共接口,就是provider 和 openfeign中公共的部分:
public interface UserService {
@GetMapping("/hello") String hello();
@GetMapping("/hello2") String hello2(@RequestParam("name") String name);
@PostMapping("/user2") User addUser2(@RequestBody User user);
@DeleteMapping("/user14/{id}") void deleteUser2(@PathVariable("id") Integer id);
@GetMapping("/user3") void getUserByName(@RequestHeader("name") String name) throws UnsupportedEncodingException; }
|
接着在provider 和 openfeign 中,分别引用该模块:
<dependency> <groupId>com.example</groupId> <artifactId>first-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
|
添加成功后,在 provider 中实现该接口:
@RestController public class HelloController implements UserService { @Value("${server.port}") Integer port; @GetMapping("/hello") @Override public String hello(){ return "hello 你好"+port; }
@GetMapping("/hello2") @Override public String hello2(String name){ return "hello "+name; }
@PostMapping("/user1") public User addUser1(User user){ return user; }
@PostMapping("/user2") @Override public User addUser2(@RequestBody User user){ return user; }
@PutMapping("/user11") public void updateUser1(User user1){ System.out.println(user1); }
@PutMapping("/user12") public void updateUser2(@RequestBody User user2){ System.out.println(user2); }
@DeleteMapping("/user13") public void deleteUser1(Integer id){ System.out.println(id); }
@DeleteMapping("/user14/{id}") @Override public void deleteUser2(@PathVariable Integer id){ System.out.println(id); }
@GetMapping("/user3") @Override public void getUserByName(@RequestHeader String name) throws UnsupportedEncodingException { System.out.println(URLDecoder.decode(name,"UTF-8")); } }
|
在 openfeign 中,定义接口继承自公共接口:
@FeignClient("provider") public interface HelloService entends UserService{ }
|
接下来,测试代码不变。
小结:
- 使用继承特性,代码简洁不易出错。服务端和消费端的代码统一,一改俱改,不易出错。这样会提高服务端和消费端的耦合度;
- 上面所讲的参数传递,在使用了继承之后,依然不变,参数该怎么传还是怎么传。
4.日志
加日志,查看请求调用过程,级别共分四种:
- NONE:不开启日志,默认就是这个
- BASIC:记录请求方法、URL、响应状态码、执行时间
- HEADERS:在BASIC 的基础上,加载请求/响应头
- FULL:在HEADERS基础上,再增加body 以及请求元数据
四种级别,可以通过Bean 来配置:
@SpringBootApplication @EnableFeignClients public class OpenfeignApplication {
public static void main(String[] args) { SpringApplication.run(OpenfeignApplication.class, args); }
@Bean Logger.Level loggerLevel(){ return Logger.Level.FULL; } }
|
在 application.properties 中开启日志级别:
logging.level.com.example.openfeign=debug
|
重启openfeign ,观察效果。
5.数据压缩
# 开启请求的数据压缩 feign.compression.request.enabled=true # 开启响应的数据压缩 feign.compression.response.enabled=true # 压缩的数据类型 feign.compression.request.mime-types=text/html,application/json # 压缩的数据下限,2048 表示当要传输的数据大于 2048 时,才会进行数据压缩 feign.compression.request.min-request-size=2048
|
6.OpenFeign+Hystrix
6.1 OpenFeig实际上就是对之前请求的一个封装,所以也需要服务降级等功能,首先定义服务降级的方法:
@Component @RequestMapping("/java") public class HelloServiceFallback implements HelloService {
@Override public String hello() { return "error"; }
@Override public String hello2(String name) { return "error2"; }
@Override public User addUser2(User user) { return null; }
@Override public void deleteUser2(Integer id) {
}
@Override public void getUserByName(String name) throws UnsupportedEncodingException {
} }
|
然后在 HelloService 配置服务降级类:
@FeignClient(value = "provider",fallback = HelloService.class) public interface HelloService extends UserService { }
|
在 application.properties 中开启 Hystrix.
#开启Hystrix feign.hystrix.enabled=true
|
6.2 也可以通过自定义 FallbackFactory 来实现服务降级:
@Component public class HelloServiceFallbackFactory implements FallbackFactory<HelloService> { @Override public HelloService create(Throwable throwable) { return new HelloService() { @Override public String hello() { return "error1--"; }
@Override public String hello2(String name) { return "error2--"; }
@Override public User addUser2(User user) { return null; }
@Override public void deleteUser2(Integer id) {
}
@Override public void getUserByName(String name) throws UnsupportedEncodingException {
} }; } }
|
HelloService 中配置如下:
@FeignClient(value = "provider",fallbackFactory = HelloServiceFallbackFactory.class) public interface HelloService extends UserService { }
|
访问如下:
小结:
- openfeign+hystrix降级操作 在yml中开启hystrix 在@FeignClient中实现fallbackFactory属性(需要implement FallbackFactory)
- 或fallback(实现接口implement Hello1Service添加@RequestMapping(“/xx”)作为区分)
- 两种实现方式都要添加@Component注解
项目地址:https://github.com/astronger/springcloud-simple-samples